package pl.us.ij.plugins.segmentation.commands.threshold;

import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import pl.us.ij.plugins.segmentation.Trace;
import pl.us.ij.plugins.segmentation.commands.ArrayHelper;
import pl.us.ij.plugins.segmentation.infrastructure.Command;
import pl.us.ij.plugins.segmentation.infrastructure.exceptions.BreakCommandException;

import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: Przemek
 * Date: 2010-02-28
 * Time: 16:36:40
 * To change this template use File | Settings | File Templates.
 */
public class HistogramThresholdCommand extends Command {
    @Override
    protected void processImage(FloatProcessor fp) throws BreakCommandException {

        ImageProcessor ip = fp.convertToFloat();


        float[] pixels = (float[]) ip.getPixels();

        final int maxPixel = (int) ArrayHelper.max(pixels);
        final int minPixel = (int) ArrayHelper.min(pixels);
        final int RANGE = maxPixel - minPixel + 1;
        final int SHIFT = -minPixel;

        int[][] histogramHelper = new int[RANGE][2];

        int[] histogram = getHistogram(pixels);
        Trace.log("Histogram Length: " + histogram.length);
        int[] cloneHistory = Arrays.copyOf(histogram, histogram.length);

        for (int i = 0; i < RANGE; i++) {
            histogramHelper[i][0] = -1;
        }

        int colorIndex = 0;
        for (int i = 1; i < RANGE - 1; i++) {
            if ((histogram[i - 1] >= histogram[i] && histogram[i] >= histogram[i + 1]) ||
                    (histogram[i - 1] <= histogram[i] && histogram[i] <= histogram[i + 1])) {
                cloneHistory[i] = -1;
            } else {
                histogramHelper[colorIndex][0] = histogram[i];
                histogramHelper[colorIndex][1] = i - SHIFT;
                colorIndex++;
            }
        }

        int i = 0;

        while (histogramHelper[i + 3][0] != -1) {
            if (histogramHelper[i][0] <= histogramHelper[i + 1][0] &&
                    histogramHelper[i][0] <= histogramHelper[i + 2][0] &&
                    histogramHelper[i + 1][0] <= histogramHelper[i + 3][0]) {
                i = removeTwoVertexes(i + 1, histogramHelper);
                i -= 4;
            }

            i++;
        }

        i = 0;

        while (histogramHelper[i + 3][0] != -1) {
            if ((histogramHelper[i][0] >= histogramHelper[i + 1][0]) &&
                    (histogramHelper[i][0] >= histogramHelper[i + 2][0]) &&
                    (histogramHelper[i + 1][0] >= histogramHelper[i + 3][0])) {
                i = removeTwoVertexes(i + 1, histogramHelper);
                i -= 4;
            }
            i++;
        }

        int max1 = i;
        int max2 = i;
        for (int a = 1; a < i - 1; a++) {
            if ((histogramHelper[a][0] > histogramHelper[max1][0]) &&
                    ((histogramHelper[a][0] > histogramHelper[a - 1][0]) &&
                            (histogramHelper[a][0] > histogramHelper[a + 1][0]))) {
                max2 = max1;
                max1 = a;
            } else if ((histogramHelper[a][0] > histogramHelper[max2][0]) &&
                    ((histogramHelper[a][0] > histogramHelper[a - 1][0]) &&
                            (histogramHelper[a][0] > histogramHelper[a + 1][0])))
                max2 = a;
        }

        if (histogramHelper[max1][1] < histogramHelper[max2][1]) {
            int pom = max1;
            max1 = max2;
            max2 = pom;
        }

        int min = max1;
        for (int a = max2; a < max1; a++) {
            if (histogramHelper[a][0] < histogramHelper[min][0])
                min = a;
        }

        OneLevelThresholdCommand.thresholdPixels(histogramHelper[min][1], pixels, (float)ip.getMin(), (float)ip.getMax());
    }

    private static int[] getHistogram(float[] pixels) {
        float min = 0;
        float max = 0;

        for (int i = 0; i < pixels.length; i++) {
            if (min > pixels[i])
                min = pixels[i];
            if (max < pixels[i])
                max = pixels[i];
        }

        int[] colors = new int[(int) (max - min) + 1];
        Arrays.fill(colors, 0);

        if (min < 0)
            min = -min;

        for (int i = 0; i < pixels.length; i++) {
            colors[((int) ((int) pixels[i] + min))]++;
        }

        return colors;
    }

    private static int removeTwoVertexes(int index, int[][] histogramHelper) {
        histogramHelper[index][0] = -1;
        histogramHelper[index + 1][0] = -1;

        while (histogramHelper[index + 2][0] != -1) {
            histogramHelper[index][0] = histogramHelper[index + 2][0];
            histogramHelper[index][1] = histogramHelper[index + 2][1];
            histogramHelper[index + 2][0] = -1;

            index++;
        }

        return index;
    }
}
